ハンドシェイクパターンの基礎 - Noise Protocol Framework (5)
定義
最初に用語の定義をします。
メッセージパターン
"e", "s", "ee", "es", "se", "ss", "psk"からなるメッセージ(トークンという呼び方をしてます)の配列です。
ハンドシェイクパターンを構成するもののうちの1つです。
それぞれの意味は以下の通りです。
e: 一時公開鍵が送信されます
s: 静的公開鍵が送信されます
ee, es, se, ss: 鍵交換が行われたことを示します
psk: 事前共有対称鍵(pre-shared symmetric key)が送信されます
プレメッセージパターン
メッセージパターンと似ていますが、こちらは"e", "s", "e, s", ""(空)のトークンのうちのいずれかをとります。メッセージパターンとは異なり配列ではありません。
ハンドシェイクパターンを構成するもののうちの1つです。
これが""(空)でない場合は、ハンドシェイクを行う前に何らかの方法で公開鍵(e: 一時的公開鍵、s: 静的公開鍵)が相手に通知されていることを意味します。
ハンドシェイクパターンは以下の3つから構成されます。
イニシエーターのプレメッセージパターン。イニシエーターの公開鍵がレスポンダーに通知されていることを意味します。
レスポンダーのプレメッセージパターン。レスポンダーの公開鍵がイニシエーターに通知されていることを意味します。
一連のメッセージパターン
最初のハンドシェイクメッセージは、基本的にはイニシエーターからレスポンダーに送信されます。 その次のメッセージはレスポンダーから、その次のメッセージはイニシエーターから・・・などのように交互に送信されます。
例
以下のハンドシェイクパターンは、2つのメッセージパターン("e"と"e, ee")だけで構成される認証されていないDHハンドシェイクを表しています。
NN:
-> e
<- e, ee
次のハンドシェイクパターンでは、イニシエーターとレスポンダーの両方が静的公開鍵のペアを交換するハンドシェイクを表します。ハンドシェイクパターンは3つのメッセージパターンで構成されています。
XX:
-> e
<- e, ee, s, es
-> s, se
2つの例にある"NN"や"XX"はパターンの名称です。この命名ルールについては後述します。
ハンドシェイクパターンがプレメッセージパターンを持つ場合は、区切り文字 "..."の前がプレメッセージパターンを表します。 両方の当事者がプレメッセージを持っている場合は、イニシエーターのプレメッセージパターンが最初に表示されます。以下の例では、両方の当事者が他方の静的公開鍵について事前に知っています。 最初の2行(-> s と <- s)がプレメッセージパターンです。
KK:
-> s
<- s
...
-> e, es, ss
<- e, ee, se
AliceとBob
ハンドシェイクパターンの定義のところで、「最初のハンドシェイクメッセージは、【基本的には】イニシエーターからレスポンダーに送信されます。」と書きました。実際、上にあげたすべてのハンドシェイクパターンの例では、イニシエーターは左側のパーティ(右向きの矢印で送信)、レスポンダーは右側でした。
しかし、複合プロトコル(Compound Protocol)と呼ばれるプロトコルでは、ハンドシェイクを確立する際に複数のNoiseプロトコルが使用されることがあり、1つのNoiseプロトコル内のレスポンダが、その後のNoiseプロトコルのイニシエータになる可能性があります。
この場合の用語と表記法の便宜のために、イニシエーターとレスポンダーの役割とは異なるアリスとボブの役割の概念を導入します。アリスを左側のパーティとみなし(右矢印でメッセージを送信)、ボブを右側のパーティとみなします。
標準形式(すなわち、アリス開始形式)で書かれたハンドシェイクパターンは、イニシエーターがアリス(最も左のパーティ)であると仮定します。 これまでのすべての説明では、標準形式のハンドシェイクパターンを想定してきました。
しかし、ハンドシェイクパターンは、矢印とトークンを逆にすることによって(例えば、"es"を"se"に置換すること、およびその逆)ボブによって開始された形式で書くこともできます。
以下は、ボブ開始形式で書いたハンドシェイクパターンの例です。
NN:
<- e
-> e, ee
XX:
<- e
-> e, ee, s, se
<- s, es
NK:
-> s
...
<- e, se
-> e, ee
KK:
<- s
-> s
...
<- e, se, ss
-> e, ee, es
ハンドシェイクパターンの妥当性検証
ハンドシェイクパターンは以下の意味で"妥当(valid)"でなければいけません。
当事者は、自分が所有する秘密鍵と公開鍵の間でのみDHを実行できます。
当事者は、ハンドシェイクごとに静的公開鍵または一時公開鍵を2回以上送信してはいけません(つまり、プレメッセージを含め、送信されるメッセージに "e"が1回、 "s"が1回しか含まれません)
当事者は、ハンドシェイクごとに複数回DH計算を実行してはいけません(すなわち、ハンドシェイクごとに"ee", "es", "se", "ss"が複数回発生してはいけません)。
リモート公開鍵(静的または一時)とローカル静的鍵の間でDHを実行した後、ローカルの当事者は、ローカル一時鍵とリモート公開鍵の間でもDHを実行していない限り、ENCRYPT()(暗号化の関数)を呼び出してはいけません。特にこれは次のことを意味します。
"se"トークンの後、"ee"トークンがない限り、イニシエーターはハンドシェイクペイロードまたはトランスポートペイロードを送信してはいけません。
"ss"トークンの後、"es"トークンがない限り、イニシエーターはハンドシェイクペイロードまたはトランスポートペイロードを送信してはいけません。
"es"トークンの後、"ee"トークンがない限り、レスポンダーはハンドシェイクペイロードまたはトランスポートペイロードを送信してはいけません。
"ss"トークンの後、"se"トークンがない限り、レスポンダーはハンドシェイクペイロードまたはトランスポートペイロードを送信してはいけません。
最初のチェックに失敗したパターンは明らかに無意味です。
2番目と3番目のチェックは、実装とテストを単純化するために冗長な送信や計算を禁止しています。
4番目のチェックの目的は2つあります。
まず、Noiseは共有秘密鍵をランダム化するために一時公開鍵を使ったDHの結果を利用しているためです。 このチェックに失敗したパターンは、鍵の再利用において壊滅的な結果をもたらす可能性があります。なぜなら、ローカルな一時鍵を使わない共通鍵で暗号化されたメッセージを送信する可能性があるからです。
第二に、このチェックは一時秘密鍵が前方秘匿性(Forward secrecy)や鍵漏洩の偽装耐性などの重要なセキュリティ特性を提供するために使用されることを保証します。
ユーザーは、後ほどあげるハンドシェイクパターン、または上記のチェックを満たすために専門家によって吟味された他のパターンのみを使用することをお勧めします。